import * as THREE from 'three';
import M from 'scripts/main.js';
import { TWEEN } from 'three/addons/libs/tween.module.min.js';
import { CSS3DRenderer, CSS3DObject } from 'three/addons/renderers/CSS3DRenderer.js';
import {School} from 'scripts/school.js';

class Lesson {
	constructor(index){	
		THREE.Cache.enabled = true;
		let books,book,animationID;

		let camera, scene, renderer,container,mouse,table,history;
		let showTranslate=0, showRandom=false,stage=0,step=0,randomArr=[];
		let cursorR,cursorL,fromJu,toJu,currentJu,isLoop=false,playing,juArr=[],isMan=true,playTimer,ziTimer,pinyin={};
		let objects = [],targets = [],lines = [];
		const m = new M();
		init();

		/*
		* 初始化
		*/
		function init() {
			books = m.loadItem("books");
			books = JSON.parse(books);
			for(let i=0;i<books.length;i++){
				if (books[i].index == index) {
					book = books[i];
					break;
				}
			}
			//TODO:目前是从本地缓存载入语音评测初始值，将来要改为从数据库中取得
			history = m.loadItem("history-zi"+book.index);
			if (!history) history = [];
			else history = JSON.parse(history);
			//返回按钮
			m.display("goback",true);
			m.getNode("goback").addEventListener('pointerdown', goback);
			//修改屏幕
			window.addEventListener( 'resize', onWindowResize );

			//创建摄像机
			camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1000, 10000 );
			camera.position.z = 6000;

			//创建场景
			scene = new THREE.Scene();

			//创建右侧的控制盘
			const control = m.newNode( 'div' );
			control.className="lesson";
			//每个字的语音评测成绩表
			table = m.newNode( 'table' );
			table.className="result";
			control.appendChild(table);
			for(let i=0;i<7;i++){
				let tr = m.newNode( 'tr' );
				table.appendChild(tr);
				for(let j=0;j<3;j++){
					let td = m.newNode( 'td' );
					tr.appendChild(td);
					if (i==0 && j==1) td.innerText="最佳";
					if (i==0 && j==2) td.innerText="本次";
					if (i==1 && j==0) td.innerText="总分";
					if (i==2 && j==0) td.innerText="发音";
					if (i==3 && j==0) td.innerText="声调";
					if (i==4 && j==0) td.innerText="流畅";
					if (i==5 && j==0) td.innerText="声母";
					if (i==6 && j==0) td.innerText="韵母";
				}
			}

			//显示成绩的区域
			const learnScore = m.newNode( 'div' );
			learnScore.className="learnScore";
			control.appendChild(learnScore);

			//显示录音频谱的区域
			const wave = m.newNode( 'div' );
			wave.className="recwave";
			control.appendChild(wave);

			//显示播放按钮
			const replayBtn = m.newNode( 'div' );
			replayBtn.innerText="▶";
			replayBtn.className="replayButton";
			control.appendChild(replayBtn);
			replayBtn.addEventListener('pointerdown', replay);

			//显示词按钮
			const ciBtn = m.newNode( 'div' );
			ciBtn.innerText="词";
			ciBtn.className="learnButton";
			ciBtn.style.top = "50px";
			ciBtn.style.left = "30px";
			control.appendChild(ciBtn);
			ciBtn.addEventListener('pointerdown', ciPage);

			//显示句按钮
			const juBtn = m.newNode( 'div' );
			juBtn.innerText="句";
			juBtn.className="learnButton";
			juBtn.style.top = "50px";
			juBtn.style.left = "70px";
			control.appendChild(juBtn);
			juBtn.addEventListener('pointerdown', juPage);

			//显示文按钮
			const wenBtn = m.newNode( 'div' );
			wenBtn.innerText="文";
			wenBtn.className="learnButton";
			wenBtn.style.top = "50px";
			wenBtn.style.left = "110px";
			control.appendChild(wenBtn);
			wenBtn.addEventListener('pointerdown', wenPage);

			//显示写按钮
			const xieBtn = m.newNode( 'div' );
			xieBtn.innerText="写";
			xieBtn.className="learnButton";
			xieBtn.style.top = "50px";
			xieBtn.style.left = "150px";
			control.appendChild(xieBtn);
			xieBtn.addEventListener('pointerdown', xiePage);

			//显示读按钮
			const duBtn = m.newNode( 'div' );
			duBtn.innerText="读";
			duBtn.className="learnButton";
			duBtn.style.top = "50px";
			duBtn.style.left = "190px";
			control.appendChild(duBtn);
			duBtn.addEventListener('pointerdown', read);
			
			//载入男女声各四句
			for(let i=0;i<4;i++){
				const ju = new Howl({
				  src: ['https://debug.smwho.com/sound/ju/1/m/'+m.parseString4(book.id,4)+""+i+'.mp3'],
    			onend: onCompletion
				});
				juArr.push(ju);
			}
			for(let i=0;i<4;i++){
				const ju = new Howl({
				  src: ['https://debug.smwho.com/sound/ju/1/f/'+m.parseString4(book.id,4)+""+i+'.mp3'],
    			onend: onCompletion
				});
				juArr.push(ju);
			}

			//显示下一步按钮
			const nextBtn = m.newNode( 'div' );
			nextBtn.innerText="▶️";
			nextBtn.className="learnButton";
			nextBtn.style.top = "90px";
			nextBtn.style.left = "30px";
			control.appendChild(nextBtn);
			nextBtn.addEventListener('pointerdown', next);

			//显示下一环节按钮
			const skipBtn = m.newNode( 'div' );
			skipBtn.innerText="⏩️";
			skipBtn.className="learnButton";
			skipBtn.style.top = "90px";
			skipBtn.style.left = "70px";
			control.appendChild(skipBtn);
			skipBtn.addEventListener('pointerdown', skip);

			//显示乱序按钮
			const randomBtn = m.newNode( 'div' );
			randomBtn.innerText="🔀️";
			randomBtn.className="learnButton";
			randomBtn.style.top = "90px";
			randomBtn.style.left = "110px";
			control.appendChild(randomBtn);
			randomBtn.addEventListener('pointerdown', random);

			//显示翻译按钮
			const translateBtn = m.newNode( 'div' );
			translateBtn.innerText="↔️";
			translateBtn.className="learnButton";
			translateBtn.style.top = "90px";
			translateBtn.style.left = "150px";
			control.appendChild(translateBtn);
			translateBtn.addEventListener('pointerdown', translate);

			//显示复位按钮
			const resetBtn = m.newNode( 'div' );
			resetBtn.innerText="🔄";
			resetBtn.className="learnButton";
			resetBtn.style.top = "90px";
			resetBtn.style.left = "190px";
			control.appendChild(resetBtn);
			resetBtn.addEventListener('pointerdown', reset);

			//显示复位按钮
			const microphone = m.newNode( 'div' );
			microphone.innerText="🎤";
			microphone.className="microphone";
			control.appendChild(microphone);
			microphone.addEventListener('pointerdown', recStart);
			microphone.addEventListener('pointerup', recStop);

			//创建在场景中显示的对象
			const CSS = new CSS3DObject( control );
			control.parent = CSS;
			//设置初始位置
			CSS.position.x = 0;
			CSS.position.y = 0;
			CSS.position.z = 6500;
			//加入场景
			scene.add( CSS );
			//加入动画列表
			objects.push( CSS );

			//动画结束时的位置
			const target = new THREE.Object3D();
			target.position.x = 280;
			target.position.y = -15;
			target.position.z = 5200;
			targets.push( target );

			//成绩初始化
			for ( let i = 0; i < book.zis.length; i ++ ) {
				//设定语音评测初始值
				let z = getHistory(i);
				
				const line = m.newNode( 'div' );
				line.className = 'ziCardLine';
				const lineCSS = new CSS3DObject( line );
				//设定初始位置
				lineCSS.position.x = (i%4)*120+5-300;
				lineCSS.position.y = 160-Math.floor(i/4)*120+5;
				lineCSS.position.z = 6500;
				//将每个线框加入场景
				scene.add( lineCSS );
				//加入数组
				lines.push( lineCSS );

				const div = m.newNode( 'div' );
				div.className = 'ziCard';
				const zi = m.newNode( 'div' );
				zi.className = 'zi';
				zi.textContent = book.zis[i].zi;
				div.appendChild(zi);

				const diao = m.newNode( 'div' );
				diao.className = 'diao';
				diao.textContent = m.getDiao(book.zis[i].d);
				div.appendChild(diao);

				const translate = m.newNode( 'div' );
				translate.className = 'translate';
				translate.textContent = book.zis[i].m.split(";")[0];
				div.appendChild(translate);

				div.tag = book.zis[i];
				div.index = i;
				div.addEventListener('mousedown', onPointerDown);
				div.addEventListener('touchstart', onPointerDown);
				div.addEventListener('mouseup', onPointerUp);
				div.addEventListener('touchend', onPointerUp);
				//载入男声
				const audiom = new Howl({
				  src: ['https://debug.smwho.com/sound/zi/m/'+book.zis[i].sound+'.mp3'],
				});
				//载入女声
				const audiof = new Howl({
				  src: ['https://debug.smwho.com/sound/zi/f/'+book.zis[i].sound+'.mp3'],
				});
				div.audio = [audiom,audiof];
				//默认先发男声
				div.man = true;
				//根据历史得分显示不同颜色的进度条
				const pb = m.newNode( 'div' );
				pb.className = 'progressBar';
      	pb.style.width=z.overall+"px";
      	pb.style.backgroundColor = getColor(z.overall);
				div.appendChild(pb);

				//创建场景中的对象
				const objectCSS = new CSS3DObject( div );
				//将控制页和显示对象建立关联
				div.parent = objectCSS;
				//设定初始位置
				objectCSS.position.x = 0;
				objectCSS.position.y = 0;
				objectCSS.position.z = 6500;
				//将每个字加入场景
				scene.add( objectCSS );
				//加入动画数组
				objects.push( objectCSS );

				//创建动画结束时的位置
				const object = new THREE.Object3D();
				object.position.x = (i%4)*120+5-300;
				object.position.y = 160-Math.floor(i/4)*120+5;
				object.position.z = 5200;
				targets.push( object );				
			}
			
			//创建选定文字的游标
			let cursor = m.newNode( 'div' );
			cursor.className = 'cursor';
			cursor.innerText="▶";
			cursorL = new CSS3DObject(cursor);
			cursorL.position.x = 0;
			cursorL.position.y = 0;
			cursorL.position.z = 6500;
			scene.add( cursorL );
			cursor = m.newNode( 'div' );
			cursor.className = 'cursor';
			cursor.innerText="◀";
			cursorR = new CSS3DObject(cursor);
			cursorR.position.x = 0;
			cursorR.position.y = 0;
			cursorR.position.z = 6500;
			scene.add( cursorR );
			
			//设置渲染器，并指定渲染位置
			renderer = new CSS3DRenderer();
			renderer.setSize( window.innerWidth, window.innerHeight );
			m.getNode( 'container' ).appendChild( renderer.domElement );
			//显示开场动画
			transform(objects, targets, 2000 );
			//动画结束后显示线框
			setTimeout(()=>{showLine(true)},2000);
			//给录音机设定显示频谱的区域
			m.recOpen("recwave");
			//开始动画
			animate();
		}
		/*
		* 显示或隐藏线框
		*/
		function showLine(show){
			for(let i=0;i<book.zis.length;i++){
				lines[i].position.z = show?6500:5200;
			}
		}
		/*
		* 打开词语页
		*/
		function ciPage(){
			
		}
		/*
		* 打开句式页
		*/
		function juPage(){
			
		}
		/*
		* 打开短文页
		*/
		function wenPage(){
			
		}
		/*
		* 打开书写页
		*/
		function xiePage(){
			
		}
		/*
		* 循环播放所有句子
		*/
		function read(){
			if (this.tag){
				this.tag=null;
				if (ziTimer) clearTimeout(ziTimer);
				if (playTimer) clearTimeout(playTimer);
				if (playing) playing.stop();
			}else{
				this.tag=true;
				fromJu=0;
				toJu=3;
				currentJu = fromJu;
				isLoop=true;
				playJu();
			}
		}
		/*
		* 跳到下一个学习步骤
		*/
		function next(){
			if (stage==0){
				//朗读阶段，每个片段朗读三次
				if(step < 3){
					fromJu = toJu = 0;
				}else if(step < 6){
					fromJu = toJu = 1;
				}else if(step < 9){
					fromJu = 0;
					toJu = 1;
				}else if(step < 12){
					fromJu = toJu = 2;
				}else if(step < 15){
					fromJu = toJu = 3;
				}else if(step < 18){
					fromJu = 2;
					toJu = 3;
				}else{
					fromJu = 0;
					toJu = 3;
				}
				currentJu = fromJu;
				playJu();
				step++;
			}else if (stage==1){
				//背诵阶段
				setFromTo(1,16);
				let tags = [];
				let objs = []
				if (step<4){
					//每次隐藏一半
					for ( let i = 0; i < book.zis.length; i++) {
						if (i%(Math.pow(2,step+1))!=0){
							objs.push(objects[i+1]);
							const tag = new THREE.Object3D();
							tag.position.x = Math.random()*4000-2000;
							tag.position.y = Math.random()*4000-2000;
							tag.position.z = 6500;
							tags.push( tag );				
						}
					}
					transform(objs, tags, 500 );
				}else{
					//最后全部显示
					transform(objects, targets, 500 );
				}
				step++;
				if (step>4) step=0;
			}else if (stage>1 && stage<5){
				//切片阶段
				let tags = [];
				let objs = []
				let c = 4;					//显示4字
				if (stage==3) c=2;	//显示2字
				if (stage==4) c=1;	//显示1字
				const r = getRandom(Math.pow(2,stage));
				setFromTo(r*c+1,(r+1)*c);
				for ( let i = 0; i < book.zis.length; i++) {
					objs.push(objects[i+1]);
					const tag = new THREE.Object3D();
					if (Math.floor(i/c) != r){
						tag.position.x = Math.random()*4000-2000;
						tag.position.y = Math.random()*4000-2000;
						tag.position.z = 6500;
					}else{
						tag.position.x = (i%4)*120+5-300;
						tag.position.y = 160-Math.floor(i/4)*120+5;
						tag.position.z = 5200;
					}
					tags.push( tag );				
				}
				transform(objs, tags, 500 );
				step++;
			}else if (stage>=5){
				//固定位置阶段
				let tags = [];
				let objs = [];
				let ids = [];
				let c = 4;					//显示4字
				if (stage==6) c=1;	//显示1字
				const r = getRandom(stage==5?4:16);
				let from = -100;
				let to = -100;
				if (c==4){
					from = -295;
					to = 65;
				}
				//挑出该显示和该隐藏的字				
				for ( let i = 0; i < book.zis.length; i++) {
					objs.push(objects[i+1]);
					const tag = new THREE.Object3D();
					if (Math.floor(i/c) != r){
						tag.position.x = Math.random()*4000-2000;
						tag.position.y = Math.random()*4000-2000;
						tag.position.z = 6500;
					}else{
						ids.push(i);
						if (stage==5){
							tag.position.x = (i%4)*120+5-300;
						}else{
							tag.position.x = -100;
							from = -100;
							to = -100;
						}
						tag.position.y = 0;
						tag.position.z = 5200;
					}
					tags.push( tag );				
				}
				//这里能用标准的设置游标的方法，所以强制设定
				cursorL.position.set(from-55,0,5200);
				cursorR.position.set(to+55,0,5200);
				setPinyin(ids[0]+1,ids[ids.length-1]+1);

				transform(objs, tags, 500 );
				step++;
			}
		}
		/*
		* 跳到下一个学习阶段
		*/
		function skip(){
			stage++;
			randomArr=[];
			step=0;
			showLine(stage>4);
			if (stage>6) {
				stage=0;
				transform(objects, targets, 500 );
				setFromTo(1,16);
			}else next();
		}
		/*
		* 获取一个不重复的随机值
		*/
		function getRandom(size){
			//为保证循环获取时不会同一个字连续出现两次，将上次的最后一个字保存起来
			if (randomArr.length== size) {
				let last = randomArr[randomArr.length-1];
				randomArr=[last];
			}
			while(true){
				let r = Math.floor(Math.random()*size);
				if (randomArr.indexOf(r)==-1) {
					randomArr.push(r);
					return r;
				}
			}
		}
		/*
		* 将16个字打乱显示
		*/
		function random(){
			randomArr=[];
			setFromTo(1,16);
			showRandom=true;
			let tags = [];
			let objs = [];
			let tmp = [];
			//根据乱序的文字重新排列
			pinyin.p = "";
			pinyin.z = "";
			
			for ( let i = 0; i < book.zis.length; i++) {
				objs.push(objects[i+1]);
				const tag = new THREE.Object3D();
				const r = getRandom(16);
				tag.position.x = (r%4)*120+5-300;
				tag.position.y = 160-Math.floor(r/4)*120+5;
				tag.position.z = 5200;
				tags.push( tag );				
				tmp[r] = book.zis[i];
			}
			transform(objs, tags, 500 );
			
			for ( let i = 0; i < tmp.length; i++) {
				pinyin.z += tmp[i].zi;
				pinyin.p += " "+tmp[i].sound;
			}
			pinyin.p = pinyin.p.substr(1);
			randomArr=[];
		}
		/*
		* 显示或隐藏翻译内容
		*/
		function translate(){
			for ( let i = 0; i < book.zis.length; i ++ ) {
				let div0 = objects[i+1].element.children[0];
				let div1 = objects[i+1].element.children[1];
				let div2 = objects[i+1].element.children[2];
				if(showTranslate==0) div2.style.display = "block";
				else if(showTranslate==1) {
					div0.style.display = "none";
					div1.style.display = "none";
				}else {
					div0.style.display = "block";
					div1.style.display = "block";
					div2.style.display = "none";
				}
			}
			showTranslate++;
			if (showTranslate>2) showTranslate=0;
			render();
		}
		/*
		* 所有字恢复到初始状态
		*/
		function reset() {
			setFromTo(1,16);
			for ( let i = 0; i < book.zis.length; i ++ ) {
				objects[i+1].element.children[2].style.display = "none";
				objects[i+1].element.children[1].style.display = "block";
			}
			transform(objects, targets, 1000 );
			showTranslate = 0;
			stage = 0;
			step = 0
			showRandom=false;
		}
		/*
		* 根据选区设置游标的位置
		*/
		function setFromTo(from,to){
			let f = targets[from].position;
			let t = targets[to].position;
			cursorL.position.set(f.x-55,f.y,f.z);
			cursorR.position.set(t.x+55,t.y,t.z);
			setPinyin(from,to);
		}
		/*
		* 设置选区内的评测内容
		*/
		function setPinyin(from,to){
			pinyin.p = "";
			pinyin.z = "";
			//如果选的是单字，则直接用位置作id
			pinyin.id = from+"-"+to;
			if (from==to)	pinyin.id = from-1;
			let total=0;
			//排列出选定的字和拼音，为语音评测做准备
			for(let i=from;i<=to;i++){
				let zi = book.zis[i-1];
				pinyin.z += zi.zi;
				pinyin.p += " "+zi.sound;
				//计算选定字得到的积分总额
				total += getHistory(i-1).score; 
			}
			//更新显示
			objects[0].element.children[1].innerText = "💰 ("+total+"/"+(pinyin.z.length*2100)+")";
			//去掉第一个空格	
			pinyin.p = pinyin.p.substr(1);
			resetTable();
		}
		/*
		* 开始录音，设置评测参数
		*/
		function recStart(){
			let energy = m.loadInt("energy");
			if (energy<pinyin.z.length){
				alert("体力不足，请先补充体力，再来挑战");
				return;
			}

			mouse = event;
			mouse.time = new Date().getTime();
			if (pinyin.z.length>0){
				this.style.backgroundColor="red";
				if (pinyin.z.length==1){
					m.recStart('word.eval.cn',pinyin.z,pinyin.p);
				}else{
					m.recStart('sent.eval.cn',pinyin.z,pinyin.p);
				}
			}else{
				alert("请先选定评测内容");
			}
		}
		/*
		* 结束评测等待获取结果
		*/
		async function recStop(){
			this.style.backgroundColor="";
			if (mouse.time + 500 > new Date().getTime()){
				m.recCancel();
				alert("请按住麦克风朗读，读完后放手");
				return;
			}
			
			let data = await m.recStop();
			//TODO：评测异常处理
			
			//减去体力
			let energy = m.loadInt("energy")-pinyin.zi.length;
			m.setEnergy(energy);
			//TODO：更新课本的磨损度

			//TODO:将录音文件和得分数据保存下来
			let url = data.audioUrl;
			if (data.result.overall>0){
				//显示成绩
				resetTable(data.result);
			}else{
				alert("错得太离谱啦！");
			}
		}
		/*
		* 播放自己的录音
		*/
		function replay(){
			m.recPlay();
		}
		/*
		* 获取当前选区的历史成绩，没有则创建
		*/
		function getHistory(id){
			let rtn;
			for(let i=0 ;i<history.length;i++){
				if (history[i].id == id){
					rtn = history[i];
					return rtn;
				}
			}
			if (!rtn) {
				//没有就新建一个;
				rtn = {id:id,overall:0,pronunciation:0,tone:0,fluency:0,phonemes1:0,phonemes2:0,score:0};
				history.push(rtn);
			}
			return rtn;			
		}
		/*
		* 重新设置得分表
		*/
		function resetTable(data){
			//找出该项目的历史记录
			let z = getHistory(pinyin.id);
			if(data){
				//总分
				table.children[1].children[2].innerText = data.overall;
				if (z.overall<data.overall){
					z.overall = data.overall;
					table.children[1].children[1].innerText = data.overall;
				}

				//发音
				table.children[2].children[2].innerText = data.pronunciation;
				if(z.pronunciation<data.pronunciation) {
					z.pronunciation = data.pronunciation;
					table.children[2].children[1].innerText = data.pronunciation;
				}

				//声调
				table.children[3].children[2].innerText = data.tone;
				if(z.tone<data.tone){
					z.tone = data.tone;
					table.children[3].children[1].innerText = data.tone;
				} 

				//多字才有流畅度
				if (data.fluency){
					table.children[4].children[2].innerText = data.fluency;
					if(z.fluency<data.fluency){
						z.fluency = data.fluency;
						table.children[4].children[1].innerText = data.fluency;
					} 
				}

				//计算声母韵母得分平均值
				let s = 0;
				let sc = 0;
				let y = 0;
				let total = 0;
				let sub = 0;
				for(let i=0;i<data.words.length;i++){
					if (data.words[i].charType==0){
						//更新每个字的得分进度条和历史最好成绩，以及积分
						for(let j=0;j<book.zis.length;j++){
							let div = objects[j+1].element;
							let overall = data.words[i].scores.overall;
							if (div.tag.zi == data.words[i].word){
								let z1 = getHistory(j);
								//计算积分增量，每个字最多得2100分
								//TODO:根据课本的稀有度加成
								if(z1.score+overall>2100) {
									sub += 2100 - z.score;
									z1.score = 2100;
								}else{
									sub += overall;
									z1.score += overall;
								}
								total += z1.score;
								if (overall >= z1.overall) {
									z1.overall = data.words[i].scores.overall;
									//更新进度条
									div.children[3].style.width=overall+"px";
									div.children[3].style.backgroundColor = getColor(overall);
								}
								if (data.words[i].scores.pronunciation > z1.pronunciation) 
									z1.pronunciation = data.words[i].scores.pronunciation;
								if (data.words[i].scores.tone > z1.tone) 
									z1.tone = data.words[i].scores.tone;
								if (data.words[i].phonemes.length==1){
									//处理无声母的情况
									y+=data.words[i].phonemes[0].pronunciation;
									if (data.words[i].phonemes[0].pronunciation > z1.phonemes2 && data.words.length>1) 
										z1.phonemes2 = data.words[i].phonemes[0].pronunciation;
								}else{
									sc++;
									s+=data.words[i].phonemes[0].pronunciation;
									y+=data.words[i].phonemes[1].pronunciation;
									if (data.words[i].phonemes[0].pronunciation > z1.phonemes1 && data.words.length>1) 
										z1.phonemes1 = data.words[i].phonemes[0].pronunciation;
									if (data.words[i].phonemes[1].pronunciation > z1.phonemes2 && data.words.length>1) 
										z1.phonemes2 = data.words[i].phonemes[1].pronunciation;
								}
								break;
							}
						}
					}
				}
				//选定部分的已有积分和总积分
				objects[0].element.children[1].innerText = "💰 ("+total+"/"+(pinyin.z.length*2100)+")";
				//更新课本的完成进度
				if (book.score) book.score = sub;
				else book.score += sub;
				m.saveJson("books",books);
				//TODO：金币掉落的动画和音效
				
				//TODO：在线获取金币
				let money = m.loadInt("money") + sub;
				//更新金币栏
				m.setMoney(money);
				//声母
				if(sc>0) {
					let p1 = Math.floor(s/sc);
					table.children[5].children[2].innerText = p1;
					if(z.phonemes1<p1) {
						z.phonemes1 = p1;
						table.children[5].children[1].innerText = p1;
					}
				}
				//韵母
				let p2 = Math.floor(y/data.words.length);
				table.children[6].children[2].innerText = p2;
				if(z.phonemes2<p2) {
					z.phonemes2 = p2;
					table.children[6].children[1].innerText = p2;
				}
				m.saveJson("history-zi"+book.id,history);
			}else{
				//显示历史成绩栏
				if (z.overall>0) table.children[1].children[1].innerText = z.overall;
				else table.children[1].children[1].innerText ="";
				if (z.pronunciation>0) table.children[2].children[1].innerText = z.pronunciation;
				else table.children[2].children[1].innerText ="";
				if (z.tone>0) table.children[3].children[1].innerText = z.tone;
				else table.children[3].children[1].innerText ="";
				if (z.fluency>0) table.children[4].children[1].innerText = z.fluency;
				else table.children[4].children[1].innerText ="";
				if (z.phonemes1>0) table.children[5].children[1].innerText = z.phonemes1;
				else table.children[5].children[1].innerText ="";
				if (z.phonemes2>0) table.children[6].children[1].innerText = z.phonemes2;
				else table.children[6].children[1].innerText ="";
				table.children[1].children[2].innerText ="";
				table.children[2].children[2].innerText ="";
				table.children[3].children[2].innerText ="";
				table.children[4].children[2].innerText ="";
				table.children[5].children[2].innerText ="";
				table.children[6].children[2].innerText ="";
			}
		}
		/*
		* 根据分值获取从红到绿的颜色值
		*/
		function getColor(v){
      let sR = -2.55;
      let sG = 2.55;
			return 'rgb('+ parseInt((sR * v + 255))+ ',' + parseInt((sG * v))+ ',0)';	
		}
		/*
		* 开场动画
		*/
		function transform( objects, targets, duration ) {

			TWEEN.removeAll();

			for ( let i = 0; i < objects.length; i ++ ) {

				const object = objects[ i ];
				const target = targets[ i ];

				new TWEEN.Tween( object.position )
					.to( { x: target.position.x, y: target.position.y, z: target.position.z }, duration )
					.easing( TWEEN.Easing.Exponential.InOut )
					.start();

			}

			new TWEEN.Tween( this )
				.to( {}, duration )
				.onUpdate( render )
				.start();

		}
		/*
		* 开始滑动
		*/
		function onPointerDown( e ) {
			if (ziTimer) clearTimeout(ziTimer);
			if (playTimer) clearTimeout(playTimer);
			//如果正在评测则取消
			m.recCancel();
			if ( e.isPrimary === false ) return;
			mouse = e;
			mouse.time = new Date().getTime();
		}
		/*
		* 获取滑动结束位置，以决定从哪里读到哪里
		*/
		function onPointerUp(e) {
			if (mouse.time + 200 > new Date().getTime() && mouse.target==e.target){
				const selectedZi = mouse.target;
				
				setFromTo(selectedZi.index+1,selectedZi.index+1);
				//显示点击效果
				mouse.target.parent.position.z -=10;
				//立刻刷新
				render();
				setTimeout(()=>{
					mouse.target.parent.position.z +=10;
					render();
				},100);
				if (playing) playing.stop();
				playing = selectedZi.audio[ selectedZi.man?0:1 ];
				playing.play();
				selectedZi.man = !selectedZi.man;
			}else{
				//触屏的滑动放开逻辑居然和鼠标的不同，所以不得不采取两套不同的操作
				if (e.clientX){
					fromJu = Math.floor(mouse.target.index/4);
					toJu   = Math.floor(e.target.index/4);
				}else{
					if (e.changedTouches.length==2){
						//必须是两点触摸才能读多句
						fromJu = Math.floor(e.changedTouches[0].target.index/4);
						toJu   = Math.floor(e.changedTouches[1].target.index/4);
					}else{
						fromJu = Math.floor(e.changedTouches[0].target.index/4);
						toJu   = Math.floor(e.changedTouches[0].target.index/4);
					}
				}
				//避免反向的选择
				if (toJu<fromJu) {
					let tmp = toJu;
					toJu = fromJu;
					fromJu = tmp;
				}
				currentJu = fromJu;
				isLoop=false;
				playJu();
			}
		}		
		/*
		* 设置播放范围并且开始播放
		*/
		function playJu(){
			if (playTimer) clearTimeout(playTimer);
			if (playing) playing.stop();
			setFromTo(fromJu*4+1,toJu*4+4);
			play();
		}
		/*
		* 播放四字一句，并且模拟点击效果
		*/
		function play(){
			//找到要读的句子
			playing = juArr[(isMan?0:1)*4+currentJu];
			playing.play();
			let c;
			let i = 0;
			clickZi();
			//模拟每个字被依次点击的效果
			function clickZi(){
				c = objects[currentJu*4+1+i];
				c.position.z -=10;
				//立刻刷新
				render();
				setTimeout(()=>{c.position.z +=10},100);
				i++;
				//朗读时每个字间隔0.5秒
				if (i<4) ziTimer = setTimeout(clickZi,500);
			};
		}
		/*
		* 四字一句读完了
		*/
		function onCompletion(){
			currentJu++;
			if (currentJu==4) {
				//只有点击【读】的按钮才会循环播放
				if (isLoop) {
					isMan = !isMan;
					currentJu=0;
				}
			}
			if (currentJu<=toJu) {
				//稍稍停一下再读下一句
				playTimer = setTimeout(play,100);
			}else isMan = !isMan;
		}
		/*
		* 返回前页
		*/
		function goback(){
			destroy();
			new School();
		}
		/*
		* 调整窗口
		*/
		function onWindowResize() {
			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();
			renderer.setSize( window.innerWidth, window.innerHeight );
			render();
		}
		/*
		* 动画
		*/
		function animate() {

			animationID = requestAnimationFrame( animate );
			TWEEN.update();
			render();
		}
		/*
		* 渲染
		*/
		function render() {

			renderer.render( scene, camera );

		}
		/*
		* 释放内存
		*/
		function destroy(){
			cancelAnimationFrame(animationID)
			if (ziTimer) clearTimeout(ziTimer);
			if (playTimer) clearTimeout(playTimer);
			if (playing) playing.stop();
			scene.clear();
			m.recCancel();
			m.recClose();
			renderer.content = null;
			
			m.getNode("goback").removeEventListener('pointerdown', goback);
			window.removeEventListener( 'resize', onWindowResize );
			m.getNode( 'container' ).removeChild(renderer.domElement);
			scene = null;
			camera = null;
			renderer = null;
			juArr = null;
			objects = null;
			targets = null;
			lines = null;
		}			
	}
}
export { Lesson };